/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.editpart;

import java.util.Iterator;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.editpolicies.NonResizableEditPolicy;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.LiteralInteger;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.VisibilityKind;

import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.figures.StringFigure;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;

/**
 * 
 */
public class RelationEndDisplayEditPart extends LinkNameDisplayEditPart{

	/**
	 * The element type accepted by the associated list model.
	 * If null, any type is accepted.
	 */
	protected org.eclipse.uml2.uml.Association element;

	/**
	 * 
	 */
	protected int channel=14;

	/**
	 * 
	 */
	protected boolean end=true;//role is near of the target

	/**
	 * 
	 */
	protected boolean displayMultiplicity=true;


	/**
	 * 
	 */
	protected static String _public=" +";

	/**
	 * 
	 */
	protected static String _protected=" #";

	/**
	 * 
	 */
	protected static String _private=" -";

	/**
	 * 
	 */
	protected static String _package="~";

	/**
	 * 
	 */
	protected static String _derived="/";

	/**
	 * 
	 */
	protected static String _ordered="ordered";

	/**
	 * 
	 */
	protected static String _readonly="readOnly";

	/**
	 * 
	 */
	protected static String _subsets="subsets";

	/**
	 * 
	 */
	protected static String _redefines="redefine";

	/**
	 * 
	 */
	protected static String _unique="unique";

	/**
	 * 
	 */
	protected static String _union="union";

	/**
	 * Create a FeatureList EditPart accepting any kind from drag and drop.
	 * 
	 * @param modelManager 
	 * @param graphnode 
	 */
	public RelationEndDisplayEditPart(GraphNode graphnode,ModelManager modelManager) {
		super(graphnode,modelManager);
		Debug.debug(this,"create NameDisplayEditPart()",channel);
		this.element = null;
	}

	/**
	 * Create a FeatureList EditPart accepting specified type from drag and drop.
	 * Create a ListEditPart for a List accepting only specified element.
	 * 
	 * @param element 
	 * @param multiplicity 
	 * @param modelManager 
	 * @param elementType 	 * @param end 
	 * @param graphnode 
	 */
	public RelationEndDisplayEditPart(GraphNode graphnode,org.eclipse.uml2.uml.Association element,boolean end,
			boolean multiplicity,ModelManager modelManager) {
		super(graphnode,modelManager);
		Debug.debug(this,"create RoleDisplayEditPart("+ element+")",channel);
		this.element = element;
		displayMultiplicity=multiplicity;
		this.end=end;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public boolean isAtEnd( ) {
		return end;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.NameDisplayEditPart#createEditPolicies()
	 */
	/**
	 * 
	 */
	@Override
	protected void createEditPolicies(){
		installEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE, new NonResizableEditPolicy());
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.NameDisplayEditPart#createFigure()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	protected StringFigure createFigure() {
		if( element.getMemberEnds().size()>1){
		if (isAtEnd()){
			if( !displayMultiplicity){
				return new StringFigure(displayProperty(((Property) element.getMemberEnds().get(0))));
			}
			else{

				int min=((LiteralInteger)((Property) element.getMemberEnds().get(0)).getLowerValue()).getValue();
				int max=((LiteralUnlimitedNatural)((Property) element.getMemberEnds().get(0)).getUpperValue()).getValue();
				return new StringFigure(getMultiplicity(min,max));
			}
		}
		else{
			if( !displayMultiplicity){
				return new StringFigure(displayProperty(((Property) element.getMemberEnds().get(1))));
			}
			else{
				int min=((LiteralInteger)((Property) element.getMemberEnds().get(1)).getLowerValue()).getValue();
				int max=((LiteralUnlimitedNatural)((Property) element.getMemberEnds().get(1)).getUpperValue()).getValue();
				return new StringFigure(getMultiplicity(min,max));
			}
		}
		}
		return new StringFigure("");
	}

	/**
	 * 
	 * 
	 * @param min 
	 * @param max 
	 * 
	 * @return 
	 */
	protected String getMultiplicity(int min ,int max){
		if (min==max){return ""+min;}
		else{
			if (max!=-1){return min+".."+max;}
			else {return min+"..*";}
		}
	}

	/**
	 * 
	 * 
	 * @param p 
	 * 
	 * @return 
	 */
	protected String displayProperty(Property p){
		String result="";
		if(p.getVisibility()==VisibilityKind.PROTECTED_LITERAL){
			result=_protected;}
		if(p.getVisibility()==VisibilityKind.PRIVATE_LITERAL){
			result=_private;}
		if(p.getVisibility()==VisibilityKind.PUBLIC_LITERAL){
			result=_public;}
		if(p.getVisibility()==VisibilityKind.PACKAGE_LITERAL){
			result=_public;}
		if(p.isDerived()){
			result=result+" "+_derived;
		}
		result=result+p.getName();
		result=result+"\n"+setProperty(p);
		return result;
	}

	/**
	 * 
	 * 
	 * @param p 
	 * 
	 * @return 
	 */
	public String setProperty(Property p){
		String propModifier="";
		if (!p.isUnique() &&!p.isReadOnly() &&!p.isOrdered() &&
				!p.isUnique()&&(p.getSubsettedProperties().size()==0)) {
			propModifier="";
		} else{
			propModifier=" {";
			if (p.isReadOnly()) {
				propModifier=propModifier+_readonly+", ";
			}
			if	(p.isDerivedUnion()) {
				propModifier=propModifier+_union+", ";
			}
			if (p.isOrdered()) {
				propModifier=propModifier+_ordered+", ";
			}
			if (p.isUnique()) {
				propModifier=propModifier+_unique+", ";
			}


			if (p.getSubsettedProperties().size()!=0){
				Iterator it= p.getSubsettedProperties().iterator();
				while(it.hasNext()) {
					propModifier=propModifier+ _subsets+" "+((Property)it.next()).getName()+", ";
				}
			}
			propModifier=propModifier.substring(0, propModifier.length()-2)+"}";
		}
		return propModifier;
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.NameDisplayEditPart#getUmlElement()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	public Element getUmlElement(){
		if( element.getMemberEnds().size()>1){
			if (isAtEnd()){
				return ((Property) element.getMemberEnds().get(0));}
			else{
				return ((Property) element.getMemberEnds().get(1));
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.NameDisplayEditPart#isElementImport()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	public boolean isElementImport(){return false;}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.NameDisplayEditPart#getElementImport()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	public ElementImport getElementImport(){return null;}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.common.editpart.NameDisplayEditPart#refreshVisuals()
	 */
	/**
	 * 
	 */
	@Override
	protected void refreshVisuals() {

		StringFigure f = (StringFigure) getFigure();
		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p ,size);
		if (isAtEnd()){
			if( !displayMultiplicity){
				((StringFigure) this.getFigure()).setText(displayProperty(((Property) element.getMemberEnds().get(0))));
			}
			else{

				int min=((LiteralInteger)((Property) element.getMemberEnds().get(0)).getLowerValue()).getValue();
				int max=((LiteralUnlimitedNatural)((Property) element.getMemberEnds().get(0)).getUpperValue()).getValue();
				((StringFigure) this.getFigure()).setText(getMultiplicity(min,max));
			}
		}
		else{
			if( !displayMultiplicity){
				((StringFigure) this.getFigure()).setText(displayProperty(((Property) element.getMemberEnds().get(1))));
			}
			else{
				int min=((LiteralInteger)((Property) element.getMemberEnds().get(1)).getLowerValue()).getValue();
				int max=((LiteralUnlimitedNatural)((Property) element.getMemberEnds().get(1)).getUpperValue()).getValue();
				((StringFigure) this.getFigure()).setText(getMultiplicity(min,max));

			}
		}

		f.setVisible(this.isVisible());		
	}

	/**
	 * Return false.
	 * This method is used in {@link com.cea.papyrus.core.editpart.LayoutEditPolicy} in order to
	 * know how to compute the coordinate of a added part.
	 * @TODO move this method to more appropriate place. 
	 * @return
	 */
	@Override
	public boolean needRelativeTranslationForAddCommand()
	{
		return false;
	}

}
